using System;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Xml;
using System.Web.Services;
using System.Web.Services.Protocols;

namespace DDASProject.CEUtility
{
    public class CompressionSoapExtension : System.Web.Services.Protocols.SoapExtension
    {
        Stream oldStream;
        Stream newStream;

        public override Stream ChainStream(Stream stream)
        {
            oldStream = stream;
            newStream = new MemoryStream();
            return newStream;
        }

        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        {
            return attribute;
        }

        public override object GetInitializer(Type type)
        {
            return typeof(CompressionSoapExtension);
        }

        public override void Initialize(object initializer)
        {
            CompressionSoapExtensionAttribute attribute = (CompressionSoapExtensionAttribute)initializer;
        }

        public override void ProcessMessage(SoapMessage message)
        {
            Byte[] buffer = new Byte[2048];
            int size;

            switch(message.Stage)
            {
                case SoapMessageStage.AfterSerialize:
                    newStream.Seek(0, SeekOrigin.Begin);
                    GZipStream zipOutputStream = new GZipStream(oldStream, CompressionMode.Compress);
                    size = 2048;
                    while(true)
                    {
                        size = newStream.Read(buffer, 0, buffer.Length);
                        if(size > 0)
                            zipOutputStream.Write(buffer, 0, size);
                        else
                            break;
                    }
                    zipOutputStream.Flush();
                    zipOutputStream.Close();
                    break;

                case SoapMessageStage.BeforeDeserialize:
                    GZipStream zipInputStream = new GZipStream(oldStream, CompressionMode.Decompress);
                    size = 2048;
                    while(true)
                    {
                        size = zipInputStream.Read(buffer, 0, buffer.Length);
                        if(size > 0)
                            newStream.Write(buffer, 0, size);
                        else
                            break;
                    }
                    newStream.Flush();
                    newStream.Seek(0, SeekOrigin.Begin);
                    break;
            }
        }
    }

    #region Attribute
    [AttributeUsage(AttributeTargets.Method)]
    public class CompressionSoapExtensionAttribute : SoapExtensionAttribute
    {
        private int priority;

        public override Type ExtensionType
        {
            get { return typeof(CompressionSoapExtension); }
        }

        public override int Priority
        {
            get { return priority; }
            set { priority = value; }
        }
    }
    #endregion
}
